package cn.t.facade.android.engine.cabinet;


import cn.t.constants.CommonConstants;
import cn.t.constants.ParamConstants;
import cn.t.constants.ResponseError;
import cn.t.converter.device.CargowaySkuDTOConverter;
import cn.t.converter.order.ExceptionLogDTOConverter;
import cn.t.converter.order.GenericCabinetHandlingConverter;
import cn.t.converter.order.OrderDTOConverter;
import cn.t.converter.order.OrderDetailDTOConverter;
import cn.t.core.exception.BizException;
import cn.t.dto.device.CabinetHandlingOCDTO;
import cn.t.dto.device.CargowaySkuDTO;
import cn.t.dto.device.DeviceOpenRecordDTO;
import cn.t.dto.device.PickUpCompleteDTO;
import cn.t.dto.device.vo.OpenCloseDTO;
import cn.t.dto.device.vo.QtyVO;
import cn.t.dto.order.ReplenishmentDTO;
import cn.t.dto.order.ReplenishmentDetailDTO;
import cn.t.dto.order.WorkOrderDTO;
import cn.t.dto.order.android.OverPickupDetailDTO;
import cn.t.dto.order.android.PickupDetailDTO;
import cn.t.dto.order.base.VBaseDTO;
import cn.t.dto.order.repenlement.ReplenishmentPageDTO;
import cn.t.dto.sku.SkuDTO;
import cn.t.enums.ActionTypeEnum;
import cn.t.enums.OptionTypeEnum;
import cn.t.enums.YesOrNoEnum;
import cn.t.enums.order.ErrorEnum;
import cn.t.enums.order.ErrorTypeEnum;
import cn.t.enums.order.MsvmOrderStatusEnum;
import cn.t.facade.android.AndroidSessionFacade;
import cn.t.facade.android.DeviceCommunicationFacade;
import cn.t.facade.android.engine.CabinetHandlingStrategy;
import cn.t.facade.device.CargowaySkuFacade;
import cn.t.facade.device.DeviceDataFacade;
import cn.t.facade.device.DeviceFacade;
import cn.t.facade.device.DeviceOpenRecordFacade;
import cn.t.facade.order.ExceptionLogFacade;
import cn.t.facade.order.OrderFacade;
import cn.t.facade.order.OverPickupRecordFacade;
import cn.t.facade.order.ReplenishmentDetailFacade;
import cn.t.facade.order.ReplenishmentFacade;
import cn.t.facade.order.SynchronizeWorkOrderFacade;
import cn.t.facade.order.WorkOrderFacade;
import cn.t.facade.sku.SkuFacade;
import cn.t.facade.user.UserInfoFacade;
import cn.t.facade.user.UserSessionFacade;
import cn.t.model.device.DeviceDataDO;
import cn.t.model.order.ExceptionLogDO;
import cn.t.model.order.OrderDO;
import cn.t.model.order.OrderDetailDO;
import cn.t.model.order.OverPickNumDO;
import cn.t.service.order.ExceptionLogService;
import cn.t.service.order.OrderDetailService;
import cn.t.service.sku.SkuService;
import cn.t.utils.DateUtil;
import cn.t.utils.MsvmUtil;
import cn.t.vo.andriod.AndroidDeviceVO;
import cn.t.vo.device.DeviceBaseInfoVO;
import cn.t.vo.user.UserSessionVO;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * 取料
 *
 * @author l
 * @create 2024/7/1 19:32
 */
@Slf4j
public abstract class GenericCabinetHandlingHandler implements CabinetHandlingStrategy {
    @Resource
    protected OrderDetailService orderDetailService;
    @Resource
    private SkuService skuService;

    @Resource
    protected  UserSessionFacade userSessionFacade;
    @Resource
    protected DeviceFacade deviceFacade;
    @Autowired
    protected ObjectMapper objectMapper;
    @Resource
    private UserInfoFacade userInfoFacade;
    @Resource
    protected DeviceOpenRecordFacade deviceOpenRecordFacade;
    @Resource
    private AndroidSessionFacade androidSessionFacade;
    @Resource
    protected DeviceDataFacade deviceDataFacade;
    @Resource
    private SkuFacade skuFacade;
    @Resource
    protected ReplenishmentDetailFacade replenishmentDetailFacade;
    @Resource
    protected ReplenishmentFacade replenishmentFacade;
    @Resource
    protected WorkOrderFacade workOrderFacade;
    @Resource
    protected CargowaySkuFacade cargowaySkuFacade;
    @Resource
    protected OverPickupRecordFacade overPickupRecordFacade;
    @Resource
    private SynchronizeWorkOrderFacade synchronizeWorkOrders;
    @Resource
    protected  OrderFacade orderFacade;
    @Resource
    protected CargowaySkuDTOConverter cargowaySkuDTOConverter;

    @Resource
    protected OrderDTOConverter orderDTOConverter;
    @Resource
    protected OrderDetailDTOConverter orderDetailDTOConverter;
    @Resource
    protected ExceptionLogFacade exceptionLogFacade;
    @Resource
    protected ExceptionLogService exceptionLogService;
    @Resource
    protected DeviceCommunicationFacade deviceCommunicationFacade;
    @Resource
    protected GenericCabinetHandlingConverter converter;
    @Resource
    protected ExceptionLogDTOConverter exceptionLogDTOConverter;
    @Resource
    protected Executor executeIoExecutor;


    @Override
    public PickupDetailDTO orderClose(CabinetHandlingOCDTO model, OptionTypeEnum optionTypeEnum, UserSessionVO session) throws ExecutionException, InterruptedException {

        //  参数校验
        OpenCloseDTO openCloseWeightVO = supplementaryGoodsCheck(model, session, optionTypeEnum, ActionTypeEnum.close);
        //  更新设备记录数据
        updateDeviceData(openCloseWeightVO);
        //重力与数量的转换
        weightCount(openCloseWeightVO);

        //总单异常记录
        if (openCloseWeightVO.getQtyList() == null) {
            //生成异常记录订单留痕
            orderFacade.addOrder(openCloseWeightVO, new ArrayList<>());
            exceptionLogFacade.exceptionAdd(openCloseWeightVO, ErrorTypeEnum.ERROR26);
            return null;
        }
        //疑似未领取
        if (openCloseWeightVO.getQtyList().size() == 0) {
            //生成异常记录订单留痕
            orderFacade.addOrder(openCloseWeightVO, new ArrayList<>());
            //  异常记录
            addException(openCloseWeightVO);
            return null;
        }
        //异常判断，设置领用行异常
        pickErrLog(openCloseWeightVO);
        OrderDO orderDO = orderDTOConverter.setOderDo(openCloseWeightVO);
        List<OrderDetailDO> orderDetailList = orderDetailDTOConverter.toOderDetailList(openCloseWeightVO);
        //判断是否超领（工单 商品）
        OverPickNumDO overPickNumDO = overPickupRecordFacade.checkOverPickupAndUpdate(orderDO, orderDetailList,Boolean.TRUE);
        overPickNumDO.setOrderDetailList(orderDetailList);
        List<PickupDetailDTO.DetailVO> detailVOS = responsePickup(openCloseWeightVO);
        List<OverPickupDetailDTO> overPickupDetailList = responseOverPickup(overPickNumDO, detailVOS);
        PickupDetailDTO pickupDetailDTO = new PickupDetailDTO(detailVOS, overPickupDetailList);


        // 超领强制提交
        if (model.getOverPickupCommit() != null && model.getOverPickupCommit() == YesOrNoEnum.YES) {
            //继续执行剩余的逻辑
            log.info("超领强制提交----{}", openCloseWeightVO.getOrderSn());
        } else if (CollectionUtils.isNotEmpty(overPickupDetailList)) {
            log.info("超领提示 {} {}", openCloseWeightVO.getOrderSn(), JSON.toJSONString(overPickupDetailList));
            return pickupDetailDTO;
        }
        //todo 以后消息通道 mq
        CompletableFuture.runAsync(()->{
                processOrderInfo(openCloseWeightVO, orderDO, overPickNumDO);
        }, executeIoExecutor);
        return pickupDetailDTO;
    }

    private void processOrderInfo(OpenCloseDTO openCloseWeightVO, OrderDO orderDO, OverPickNumDO overPickNumDO) {
        List<OrderDetailDO> orderDetailList = overPickNumDO.getOrderDetailList();
        String workOrderSn = openCloseWeightVO.getWorkOrderSn();
        //  异常记录
        addException(openCloseWeightVO);

        //工单创建 非异常单创建工单
        boolean noErr = openCloseWeightVO.getQtyList().stream().allMatch(qtyVO -> qtyVO.getErrorTypeEnum() == null) && openCloseWeightVO.getErrorTypeEnum() == null;
        if (!ObjectUtils.isEmpty(orderDetailList) && noErr) {
            workOrderSn = workOrderFacade.addWorkOrder(orderDO, openCloseWeightVO.getEmployeeCode(), orderDetailList);
        }
        openCloseWeightVO.setWorkOrderSn(workOrderSn);
        //生成订单
        orderFacade.addOrder(openCloseWeightVO, orderDetailList);
        //更新货道数据 (重量和库存)
        cargowaySkuFacade.updateByOpenCloseData(openCloseWeightVO);
        //超领插入
        overPickupRecordFacade.addOverPick(overPickNumDO, orderDO);
        //超领账号锁定
        if (!ObjectUtils.isEmpty(overPickNumDO.getOverPickupList()) && YesOrNoEnum.YES.getCode().equals(openCloseWeightVO.getIsLock())) {
            log.info("超领账号锁定----{}", openCloseWeightVO.getUserId());
            userInfoFacade.disableUser(openCloseWeightVO.getUserId());
        }
        //推送工单或邮件
        synchronizeWorkOrders.synchronizeWorkOrder(orderDO, orderDetailList, overPickNumDO.getOverPickupList());
    }

    @Override
    public OpenCloseDTO openDoor(CabinetHandlingOCDTO model, OptionTypeEnum optionTypeEnum) throws ExecutionException, InterruptedException {
        UserSessionVO session = userSessionFacade.getSession();
        //  参数校验
        OpenCloseDTO openCloseWeightVO = supplementaryGoodsCheck(model, session, optionTypeEnum, ActionTypeEnum.open);
        String orderSn = MsvmUtil.getOrderSn(model.getDeviceId());
        boolean isOrder = OptionTypeEnum.order_open.equals(optionTypeEnum);
        if (isOrder) {
            openCloseWeightVO.setOrderSn(orderSn);
        }
        openCloseWeightVO.setRequestId(orderSn);

        //关门数据记录
        addDeviceData(openCloseWeightVO);
        //缓存当前用户的的历史领用情况
        if (isOrder){
            CompletableFuture.runAsync(()->{
                androidSessionFacade.setDayOverPickNumSession(openCloseWeightVO.getUserId(), openCloseWeightVO.getFirmId(),
                        openCloseWeightVO.getParticipantId(),openCloseWeightVO.getDeviceId());
            }, executeIoExecutor);
        }
        return openCloseWeightVO;
    }


    @Override
    public List<PickupDetailDTO.DetailVO> pickUpComplete(PickUpCompleteDTO model, AndroidDeviceVO device) {
        if (ObjectUtils.isEmpty(model.getOrderSn())){
            throw new BizException(ErrorEnum.ORDER_SN_MISSING,"订单号缺失,无法下单！");
        }
        UserSessionVO session = userSessionFacade.getSession();
        check(session);
        Map<Integer, CargowaySkuDTO> cargowayMap = cargowaySkuFacade.cargowayMap(device.getDeviceId());
        //订单信息查询
        OrderDO orderDO = orderFacade.getOrderDO(model.getOrderSn());
        if (CommonConstants.ZERO.equals(model.getPickUpStatus())){
            orderDO.setOrderStatus(MsvmOrderStatusEnum.NORMAL.getCode());
        }else {
            orderDO.setOrderStatus(MsvmOrderStatusEnum.ERR_ORDER.getCode());
            ExceptionLogDO exceptionLogDO = exceptionLogDTOConverter.setErrDo(model, device, session,ErrorTypeEnum.ERROR27);
            exceptionLogDO.setRemark("未正常领用的货道号有"+JSON.toJSONString(model.getNoList()));
            if (!CollectionUtils.isEmpty(model.getNoList())){
                List<ExceptionLogDO> errList = model.getNoList().stream().map
                        (no -> exceptionLogDTOConverter.pickUpdo2Exception(orderDO, cargowayMap.get(no),
                                ErrorTypeEnum.ERROR27)).collect(Collectors.toList());
                if (!org.springframework.util.ObjectUtils.isEmpty(errList)) {
                    log.info("异常记录条数量：订单号{} {}", model.getOrderSn(), errList.size());
                    exceptionLogService.saveBatch(errList);
                }
            }else {
                exceptionLogService.add(exceptionLogDO);
            }


        }
        orderFacade.update(orderDTOConverter.model2Dto(orderDO));
        //过滤出未领用的
        return responsePickup(orderDO, model.getNoList());
    }

    public List<PickupDetailDTO.DetailVO> responsePickup(OrderDO orderDO,List<Integer> noList) {
        //订单获取领用详情
        OrderDetailDO orderDetailQueryParam = new OrderDetailDO();
        orderDetailQueryParam.setOrderSn(orderDO.getOrderSn());
        List<OrderDetailDO> orderDetailDOList = orderDetailService.queryListByOrderSn(orderDetailQueryParam);
        Stream< PickupDetailDTO.DetailVO> collect = orderDetailDOList.stream().map(orderDetailDO -> cargowaySkuDTOConverter.do2PickupDetail(orderDetailDO));
        Map<Integer, CargowaySkuDTO> cargowayMap = cargowaySkuFacade.cargowayMap(orderDO.getDeviceId());
        return    Stream.concat(noList.stream().map(item -> {
                            PickupDetailDTO.DetailVO pickupDetailInfo = cargowaySkuDTOConverter.do2PickupDetail(cargowayMap.get(item));
                            if (pickupDetailInfo == null) {
                                pickupDetailInfo = new PickupDetailDTO.DetailVO();
                            }
                            //领用
                            pickupDetailInfo.setStatus("未正常领用");
                            return pickupDetailInfo;
                        }),
                        collect)
                .sorted(Comparator.comparing(PickupDetailDTO.DetailVO::getCargowayNo)).collect(Collectors.toList());
    }
    @Override
    public Boolean replenishmentGoodsClose(CabinetHandlingOCDTO model) throws ExecutionException, InterruptedException {
        UserSessionVO session = userSessionFacade.getSession();
        //  参数校验
        OpenCloseDTO openCloseWeightVO = supplementaryGoodsCheck(model, session, OptionTypeEnum.rs_open, ActionTypeEnum.close);
        //关门数据记录
        updateDeviceData(openCloseWeightVO);

        //重力与数量的转换
        weightCount(openCloseWeightVO);
        log.info("设备解析处理数据  orderClose：{}", JSON.toJSONString(openCloseWeightVO));
        //补货单异常记录
        if (openCloseWeightVO.getQtyList() == null) {
            exceptionLogFacade.exceptionAdd(openCloseWeightVO, ErrorTypeEnum.ERROR26);
            return true;
        }     //疑似未领取
        if (openCloseWeightVO.getQtyList().size() == 0) {
            //  异常记录
            addException(openCloseWeightVO);
            return true;
        }

        //补货
        VBaseDTO<ReplenishmentPageDTO, ReplenishmentDetailDTO> replenishmentVO = replenishmentDetailDTOMap(openCloseWeightVO.getOrderSn());
        Map<Integer, ReplenishmentDetailDTO> replenishmentDetailMap = replenishmentVO.getDetail().stream().collect(Collectors.toMap(ReplenishmentDetailDTO::getCargowayNo, Function.identity()));


        //行异常记录
        replenishmentErrLog(replenishmentDetailMap, openCloseWeightVO);
        addException(openCloseWeightVO);
        CompletableFuture.runAsync(() -> {
            //更新货道数据 (重量和库存)
            cargowaySkuFacade.updateByOpenCloseData(openCloseWeightVO);
        }, executeIoExecutor);
        CompletableFuture.runAsync(() -> {
            //补货状态和库存记录
            replenishmentFacade.updateStatus(replenishmentVO, openCloseWeightVO);
        }, executeIoExecutor);
        return true;
    }


    @Override
    public String replenishmentGoodsOpen(CabinetHandlingOCDTO model) throws ExecutionException, InterruptedException {
        OpenCloseDTO openCloseDTO = openDoor(model, OptionTypeEnum.rs_open);

        return openCloseDTO.getRequestId();
    }
    /**
     *开始领用
     */
   @Override
    public String startPick(CabinetHandlingOCDTO req) throws ExecutionException, InterruptedException {
        UserSessionVO session = userSessionFacade.getSession();
        //  参数校验
        OpenCloseDTO openCloseWeightVO = supplementaryGoodsCheck(req, session, OptionTypeEnum.order_open, ActionTypeEnum.create);

        openCloseWeightVO.setOrderStatus(MsvmOrderStatusEnum.NORMAL.getCode());
        //  校验库存
        weightCount(openCloseWeightVO);
        //  行异常记录
        addException(openCloseWeightVO);
        //查询sku信息
        List<String> skuCodes = openCloseWeightVO.getQtyList().stream().map(QtyVO::getSkuCode).distinct().collect(toList());
        Map<String, SkuDTO> skuMap = skuFacade.getSkuMap(skuCodes);

       String orderSn = MsvmUtil.getOrderSn(openCloseWeightVO.getDeviceId());
       openCloseWeightVO.setOrderSn(orderSn);
        // 生成订单和工单信息
       OrderDO orderDO = orderFacade.addStartInfo(openCloseWeightVO, skuMap);
       return orderDO.getOrderSn();
    }
    public OpenCloseDTO supplementaryGoodsCheck(CabinetHandlingOCDTO model, UserSessionVO session, OptionTypeEnum optionTypeEnum, ActionTypeEnum actionTypeEnum) throws ExecutionException, InterruptedException {
        if (CollectionUtils.isEmpty(model.getScale())) {
            throw new BizException(ResponseError.DATA_ERR, "货道数据异常，请联系管理员！");
        }
        OpenCloseDTO openCloseWeightVO = converter.dto2VO(model);
        openCloseWeightVO.setActionTypeEnum(actionTypeEnum);
        //用户信息检查
        check(session);
        //校验用户关门是否与开门用户是同一个
        if (ActionTypeEnum.close.equals(actionTypeEnum)) {
            List<DeviceOpenRecordDTO> deviceOpenRecordList = deviceOpenRecordFacade.getDeviceOpenRecordList(Collections.singletonList(model.getOrderSn()));
            if (ObjectUtils.isEmpty(deviceOpenRecordList)) {
                log.warn("开门数据为空,请联系管理员 {}", model.getOrderSn());
                throw new BizException(ResponseError.DATA_ERR, "开门数据为空,请联系管理员" + model.getOrderSn());
            }
            Optional<DeviceOpenRecordDTO> first = deviceOpenRecordList.stream().filter(deviceOpenRecordDTO -> deviceOpenRecordDTO.getBusinessType().equals(optionTypeEnum.getCode())
                    && deviceOpenRecordDTO.getGmtOpen() != null).max(Comparator.comparing(DeviceOpenRecordDTO::getGmtOpen));
            if (first.isPresent()) {
                openCloseWeightVO.setOpenRecordAt(first.get().getGmtOpen());
                openCloseWeightVO.setOpenRecordId(first.get().getId());
            } else {
                throw new BizException(ResponseError.DATA_ERR, "开门数据为空,请联系管理员" + model.getOrderSn());

            }
            //非同一个用户操作
            boolean isUser = deviceOpenRecordList.stream().anyMatch(deviceOpenRecordDTO -> !deviceOpenRecordDTO.getUserId().equals(session.getUserId()));
            if (isUser) {
                log.warn("用户关门与开门用户不是同一个" + model.getOrderSn());
                throw new BizException(ResponseError.DATA_ERR, "用户开关门数据不一致" + model.getOrderSn());
            }
        }
        //工单检查
        if (model.getWorkOrderSn() != null) {
            WorkOrderDTO workOrderDTO = new WorkOrderDTO();
            workOrderDTO.setWorkOrderSn(model.getWorkOrderSn());
            List<WorkOrderDTO> workOrder = workOrderFacade.queryList(workOrderDTO, ParamConstants.INT_0, ParamConstants.INT_1, "gmt_created", " desc");
            if (ObjectUtils.isEmpty(workOrder)) {
                log.warn("工单不存在" + model.getWorkOrderSn());
                throw new BizException(ResponseError.DATA_ERR, "工单不存在" + model.getWorkOrderSn());
            }
        }
        //校验重力数据
        List<DeviceDataDO> dataByOrderSn = deviceDataFacade.findDataByOrderSn(openCloseWeightVO, optionTypeEnum, DateUtil.dateByStr(model.getRecordAt()));
        if (!ObjectUtils.isEmpty(dataByOrderSn)) {
            throw new BizException(ResponseError.DATA_ERR, "重复处理" + dataByOrderSn.get(0).getOrderSn());
        }
        if (optionTypeEnum.equals(OptionTypeEnum.rs_open)) {
            //补货信息
            ReplenishmentDTO replenishmentDO = new ReplenishmentDTO(model.getOrderSn().trim(), model.getDeviceId());
            List<ReplenishmentDTO> repositoryList = replenishmentFacade.queryList(replenishmentDO, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);
            if (CollectionUtils.isEmpty(repositoryList)) {
                throw new BizException(ResponseError.RS_DATA_NOTFOUND_ERR, ResponseError.RS_DATA_NOTFOUND_ERR.getName());
            }
        }

        //设备检查
        CompletableFuture<DeviceBaseInfoVO> deviceCompletableFuture = CompletableFuture.supplyAsync(() -> deviceFacade.deviceBaseInfo(model.getDeviceId()), executeIoExecutor);

        //货道库存检查
        CompletableFuture<Map<Integer, CargowaySkuDTO>> cargowaySkuMapCompletableFuture = CompletableFuture.supplyAsync(() -> cargowaySkuFacade.cargowayMap(model.getDeviceId()), executeIoExecutor);
        DeviceBaseInfoVO device = deviceCompletableFuture.get();

        //set data
        converter.setCloseOpenData(openCloseWeightVO, device, session);
        //货道sku信息
        openCloseWeightVO.setCargowaySkuMap(cargowaySkuMapCompletableFuture.get());

        //操作类型
        openCloseWeightVO.setOptionTypeEnum(optionTypeEnum);
        return openCloseWeightVO;
    }

    public void check(UserSessionVO session) {
        //校验用户状态
        if (ObjectUtils.isEmpty(session)) {
            throw new BizException(ResponseError.LOGIN_ERR, "请重新登录");

        }
    }


    public VBaseDTO<ReplenishmentPageDTO, ReplenishmentDetailDTO> replenishmentDetailDTOMap(String rsSn) {
        ReplenishmentPageDTO replenishmentInfo = replenishmentFacade.findReplenishmentInfo(rsSn);
        List<ReplenishmentDetailDTO> replenishmentDetailList = replenishmentDetailFacade.getReplenishmentDetailList(Collections.singletonList(rsSn));
        return new VBaseDTO<>(replenishmentInfo, replenishmentDetailList);

    }

    private void addDeviceData(OpenCloseDTO openCloseWeightVO) {
        CompletableFuture<Void> voidCompletableFuture2 = CompletableFuture.runAsync(() -> {
            //货道重力库存更新
            cargowaySkuFacade.updateByOpenCloseData(openCloseWeightVO);
        }, executeIoExecutor);
        CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
            //开门记录
            deviceOpenRecordFacade.addInfo(openCloseWeightVO);
        }, executeIoExecutor);
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            //设备数据
            deviceDataFacade.addInfo(openCloseWeightVO);
        }, executeIoExecutor);
        Void join = CompletableFuture.allOf(voidCompletableFuture, voidCompletableFuture1, voidCompletableFuture2).join();
    }

    public void updateSingleDeviceData(OpenCloseDTO openCloseWeightVO) {
            //开门记录
            deviceOpenRecordFacade.updateInfo(openCloseWeightVO);
            //设备数据
            deviceDataFacade.addInfo(openCloseWeightVO);

    }
    private void updateDeviceData(OpenCloseDTO openCloseWeightVO) {
        CompletableFuture<Void> voidCompletableFuture2 = CompletableFuture.runAsync(() -> {
            //货道重力库存更新
            cargowaySkuFacade.updateByOpenCloseData(openCloseWeightVO);
        }, executeIoExecutor);
        CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
            //开门记录
            deviceOpenRecordFacade.updateInfo(openCloseWeightVO);
        }, executeIoExecutor);
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            //设备数据
            deviceDataFacade.addInfo(openCloseWeightVO);
        }, executeIoExecutor);
        Void join = CompletableFuture.allOf(voidCompletableFuture, voidCompletableFuture1, voidCompletableFuture2).join();
    }

    public abstract void weightCount(OpenCloseDTO model);
    public abstract void addException(OpenCloseDTO model);

    public abstract void replenishmentErrLog(Map<Integer, ReplenishmentDetailDTO> detailMap, OpenCloseDTO openCloseDO);

    public abstract List<PickupDetailDTO.DetailVO> responsePickup(OpenCloseDTO openCloseDO);

    public abstract List<OverPickupDetailDTO> responseOverPickup(OverPickNumDO overPickNumDO, List<PickupDetailDTO.DetailVO> detailVOS);

    public abstract void pickErrLog(OpenCloseDTO openCloseDO);
}
